{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ffdb5b70",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "import smtplib\n",
    "from email.mime.text import MIMEText"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "720a5d9e",
   "metadata": {},
   "source": [
    "### 数据发送至邮箱\n",
    "- 参考文章：https://blog.csdn.net/hot7732788/article/details/121247711"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "058f1930",
   "metadata": {},
   "outputs": [],
   "source": [
    "import smtplib\n",
    "from email.mime.text import MIMEText\n",
    "from email.mime.image import MIMEImage\n",
    "from email.mime.multipart import MIMEMultipart\n",
    "from email.mime.application import MIMEApplication\n",
    "\n",
    "\n",
    "def send_email(text, server=\"smtp.163.com\", sender=None, receivers=None, psw=None, attachment=None, to=\"收件人\",subject=\"python自动发送邮件\"):\n",
    "    \"\"\"\n",
    "    text:邮件内容\n",
    "    server：发送邮件服务方，默认为163服务方\n",
    "    sender：发送人\n",
    "    receivers：接收人，多个接收人封装为列表\n",
    "    psw：从163邮箱获取的服务密码\n",
    "    attachment：附件，单个附件地址，或者多个附件地址列表\n",
    "    to：收件人名称\n",
    "    subject：邮件主题\n",
    "    \"\"\"\n",
    "    # 实例化一个邮箱对象\n",
    "    smtp = smtplib.SMTP()\n",
    "    # 发送的文本内容\n",
    "    text = f'<p>{text}</p>'\n",
    "    # 实例化一个发送文本的邮箱对象\n",
    "    mime_text = MIMEText(_text=text, _subtype=\"html\", _charset=\"utf-8\")\n",
    "    # 发件人\n",
    "    mime_text[\"from\"] = sender\n",
    "    # 收件人\n",
    "    mime_text[\"to\"] = to\n",
    "    # 主题\n",
    "    # mime_text[\"subject\"] = subject\n",
    "    # 创建一个多部分的邮箱对象\n",
    "    mime_multipart = MIMEMultipart()\n",
    "    # 邮箱主题\n",
    "    mime_multipart['Subject'] = subject\n",
    "    mime_multipart.attach(mime_text)\n",
    "    if attachment:\n",
    "        # 发送附件\n",
    "        if isinstance(attachment, str):\n",
    "            # 单个附件地址\n",
    "            with open(attachment, 'rb') as f:\n",
    "                mime_application = MIMEApplication(f.read())\n",
    "                mime_application.add_header('Content-Disposition', 'attachment', filename=attachment)\n",
    "                mime_multipart.attach(mime_application)\n",
    "        elif isinstance(attachment, list):\n",
    "            # 多个附件地址列表\n",
    "            for file in attachment:\n",
    "                with open(file, 'rb') as f:\n",
    "                    mime_application = MIMEApplication(f.read())\n",
    "                    mime_application.add_header('Content-Disposition', 'attachment', filename=file)\n",
    "                    mime_multipart.attach(mime_application)\n",
    "    try:\n",
    "        # 连接并登录发送邮件的服务方\n",
    "        smtp.connect(server)\n",
    "        smtp.login(sender, password=psw)\n",
    "        # 发送邮件\n",
    "        smtp.sendmail(from_addr=sender, to_addrs=receivers, msg=mime_multipart.as_string())\n",
    "        print(\"发送邮件到 \", receivers, \" 成功！\")\n",
    "    except Exception as e:\n",
    "        print(str(e))\n",
    "    finally:\n",
    "        smtp.quit()\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    text = \"Python自动发送邮件\"\n",
    "    sender = 'xxxxxxxxxxx@163.com'\n",
    "    psw = 'xxxxxxxxxxxxxxxx'\n",
    "    receivers = [\"xxxxxxxxxx@qq.com\", \"xxxxxxxxxx@163.com\"]\n",
    "    # 不发送附件方式\n",
    "    # send_email(text=text,sender=sender,psw=psw,receivers=receivers)\n",
    "    # 发送单个附件\n",
    "    # attachment = \"./requirements.txt\"\n",
    "    # send_email(text=text,sender=sender,psw=psw,receivers=receivers,attachment=attachment)\n",
    "    # 发送多个附件\n",
    "    # attachment = [\"./requirements.txt\",\"./sspython.ico\"]\n",
    "    # send_email(text=text,sender=sender,psw=psw,receivers=receivers,attachment=attachment)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fb7a0045",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "074be771",
   "metadata": {},
   "source": [
    "### 钉钉消息发送数据\n",
    "- 官方文档：https://open.dingtalk.com/document/group/custom-robot-access"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9b0a5a71",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "import time\n",
    "import hmac\n",
    "import hashlib\n",
    "import base64\n",
    "import urllib.parse\n",
    "\n",
    "\n",
    "def judge_msg(key_msg_list, msg):\n",
    "    \"\"\"\n",
    "    判断发送的消息中是否包含关键字\n",
    "    \"\"\"\n",
    "    for km in key_msg_list:\n",
    "        if km in msg:\n",
    "            return True\n",
    "    return False\n",
    "\n",
    "\n",
    "def make_sign(secret=None):\n",
    "    # 当安全设置选择加签方式时，制作秘钥\n",
    "    timestamp = str(round(time.time() * 1000))\n",
    "    if secret is None:\n",
    "        return None\n",
    "    secret_enc = secret.encode('utf-8')\n",
    "    string_to_sign = '{}\\n{}'.format(timestamp, secret)\n",
    "    string_to_sign_enc = string_to_sign.encode('utf-8')\n",
    "    hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()\n",
    "    sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))\n",
    "    return timestamp, sign\n",
    "\n",
    "\n",
    "def dingding_robot(msg=None, key_msg_list=None, safe_set=None, send_type=None, secret=None, webhook=None,\n",
    "                   at_mobiles=None, at_all=False, title=\"钉钉机器人\"):\n",
    "    \"\"\"\n",
    "    钉钉机器人\n",
    "    :param title: 在消息显示的时候的简短信息\n",
    "    :param secret: 密钥\n",
    "    :param key_msg_list: 自定义的关键词列表\n",
    "    :param msg: 发送的信息\n",
    "    :param safe_set:安全设置，自定义关键词，加签\n",
    "    :param send_type: 发送内容的类型：text，markdown(md)\n",
    "    :param webhook: 申请的webhook\n",
    "    :param at_mobiles: 默认为None，指定@某人，传入列表\n",
    "    :param at_all: @所有人，传入True或者False\n",
    "    :return: 发送是否成功标志\n",
    "    \"\"\"\n",
    "    if webhook is None:\n",
    "        print(\"webhook参数为必选项\")\n",
    "        return None\n",
    "    if at_mobiles is None:\n",
    "        at_mobiles = []\n",
    "    if send_type not in [\"text\", \"md\", \"markdown\"]:\n",
    "        print(\"send_type必须为['text', 'md', 'markdown']其中一个\")\n",
    "        return None\n",
    "    if safe_set in ['自定义关键词', '加签']:\n",
    "        header = {\n",
    "            \"Content-Type\": \"application/json\",\n",
    "            \"Charset\": \"UTF-8\"\n",
    "        }\n",
    "        send_content = {\"at\": {\"atMobiles\": at_mobiles, \"isAtAll\": at_all}}\n",
    "        if send_type == \"text\":\n",
    "            send_content[\"msgtype\"] = \"text\"\n",
    "            send_content[\"text\"] = {\"content\": msg}\n",
    "        elif send_type in [\"md\", \"markdown\"]:\n",
    "            send_content[\"msgtype\"] = \"markdown\"\n",
    "            send_content[\"markdown\"] = {\"title\": title, \"text\": msg}\n",
    "        if safe_set == \"自定义关键词\":\n",
    "            if not isinstance(key_msg_list, list) and not judge_msg(key_msg_list, msg):\n",
    "                print(\"key_msg_list传入自定义的关键词列表，msg中必须包含其中一个关键词\")\n",
    "                return None\n",
    "            res = requests.post(url=webhook, json=send_content, headers=header)\n",
    "            return res.text\n",
    "        elif safe_set == \"加签\":\n",
    "            if secret:\n",
    "                timestamp, sign = make_sign(secret)\n",
    "                webhook = webhook + \"&timestamp=\" + timestamp + \"&sign=\" + sign\n",
    "                res = requests.post(url=webhook, json=send_content, headers=header)\n",
    "                return res.text\n",
    "            else:\n",
    "                print(\"secret为密钥，加签方式必须传入;\")\n",
    "                return None\n",
    "    else:\n",
    "        print(\"safe_set参数为['自定义关键词', '加签']其中一个\")\n",
    "        return None\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    # 1、安全设置为自定义关键词\n",
    "    webhook = \"从钉钉群中获取的webhook\"\n",
    "    safe_set = \"自定义关键词\"\n",
    "    key_msg_list = [\"自定义关键词1\", \"自定义关键词2\", \"自定义关键词3\"]\n",
    "    msg = \"发送的内容\"\n",
    "    send_type = \"text\"  # 或 md、或 markdown\n",
    "    at_mobiles = [\"11111111111\", \"2222222222\"]  # 默认为 None\n",
    "    dingding_robot(webhook=webhook, safe_set=safe_set, key_msg_list=key_msg_list, msg=msg, send_type=send_type,\n",
    "                   at_mobiles=at_mobiles)\n",
    "    # 2、安全设置为加签\n",
    "    # safe_set = \"加签\"\n",
    "    # secret = \"xxxxxxxxxxxxxxxxxxxxxxx\"\n",
    "    # dingding_robot(webhook=webhook, safe_set=safe_set, secret=secret, msg=msg, send_type=send_type,\n",
    "    #                at_mobiles=at_mobiles)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5f0da105",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
